#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>
#include <netdb.h> //gethostbyname()

#define DEBUG(log) printf("%s(%d):%s\n",__FUNCTION__,__LINE__,log);
#define MAX_BUFFER_SIZE 2048


int getserverreply(int socket,char *buffer,int size)
{
    int nRet;
    while(nRet=recv(socket,buffer,size,0))
    {
        if(nRet<0)
        {
            perror("server reply:");
            close(socket);
            exit(-1);
        }
        buffer[sizeof(buffer)-1]=='\0';
        printf("server --> %s",buffer);
        if(nRet !=sizeof(buffer))
        {
            break;
        }
        bzero(buffer,0);
    }
}

int sendtoserver(int socket,char *buffer,int size)
{
    
    if(send(socket,buffer,strlen(buffer),0)<0)
    {
        perror("send:");
        close(socket);
        exit(-1);
    }    
    printf("server <-- %s",buffer);
    bzero(buffer,0);
}
char* b64_encode(char *source,char *target)
{
	char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    char *p=source;
    int src_length;
    int tar_length=0;
    int i,n;
    char a ,b,c;
    src_length=strlen(source);
    for(i=0;i<src_length;i+=3)
    {
        a = source[i];
        b = (i + 1 >= src_length) ? 0 : source[i + 1];
        c = (i + 2 >= src_length) ? 0 : source[i + 2];
        if(i+2<src_length)
        {
            target[tar_length++] = (b64[(a >> 2) & 0x3F]);
            target[tar_length++] = (b64[((a << 4) & 0x30) + ((b >> 4) & 0xf)]);
            target[tar_length++] = (b64[((b << 2) & 0x3c) + ((c >> 6) & 0x3)]);
            target[tar_length++] = (b64[c & 0x3F]);
            
        }
        else if(i+1<src_length)
        {
            target[tar_length++] = (b64[(a >> 2) & 0x3F]);
            target[tar_length++] = (b64[((a << 4) & 0x30) + ((b >> 4) & 0xf)]);
            target[tar_length++] = (b64[((b << 2) & 0x3c) + ((c >> 6) & 0x3)]);
            target[tar_length++] = '=';
        }
        else
        {
            target[tar_length++] = (b64[(a >> 2) & 0x3F]);
            target[tar_length++] = (b64[((a << 4) & 0x30) + ((b >> 4) & 0xf)]);
            target[tar_length++] = '=';
            target[tar_length++] = '=';          
        }
    }
    target[tar_length]='\0';
    return target;
}
int sendmail(char *server,int port,char *username,char *password,char *subject,char *sender,char *receiver,char *cc)
{
    struct sockaddr_in servaddr;
    char buffer[MAX_BUFFER_SIZE]={0};
    char hostname[MAX_BUFFER_SIZE]={0};
    char user_name[MAX_BUFFER_SIZE]={0};
    char pass_word[MAX_BUFFER_SIZE]={0};
    struct hostent *hp;
    int mail_sock;
    int nRet;
    gethostname(hostname,sizeof(hostname));
    bzero(&servaddr,0);
    servaddr.sin_port=htons(port);
    hp=gethostbyname(server);
    servaddr.sin_family=hp->h_addrtype;
    // h_addr_list[0]
    memcpy((char *)&servaddr.sin_addr, hp->h_addr, hp->h_length);

    //socket
    if((mail_sock = socket(AF_INET,SOCK_STREAM,0))<0)
    {
        perror("socket:");
    }
    //connect
    if(connect(mail_sock,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
    {
        perror("connect:");
    }
    DEBUG("11");
    while(nRet=recv(mail_sock,buffer,sizeof(buffer)-1,0))
    {
        if(nRet<0)
        {
            perror("server reply:");
            close(mail_sock);
            exit(-1);
        }
        buffer[sizeof(buffer)-1]=='\0';
        printf("server %s --> %s",server,buffer);
        if(nRet !=sizeof(buffer))
        {
            break;
        }
        bzero(buffer,'\0');
    }
    DEBUG("11");
    
    //say hello to server
    snprintf(buffer,MAX_BUFFER_SIZE,"EHLO %s\r\n",hostname);
    //strcpy(buffer,"EHLO %s\r\n",hostname);
    //strcpy(buffer,"EHLO linux\r\n");
    if(send(mail_sock,buffer,strlen(buffer),0)<0)
    {
        perror("send:");
        close(mail_sock);
        exit(-1);
    }

    
    DEBUG("11");
    
    getserverreply(mail_sock,buffer,sizeof(buffer)-1);
    //login 
    
    snprintf(buffer,MAX_BUFFER_SIZE,"AUTH LOGIN\r\n",user_name);
    sendtoserver(mail_sock,buffer,strlen(buffer));
    getserverreply(mail_sock,buffer,MAX_BUFFER_SIZE);
    b64_encode(username,user_name);
    b64_encode(password,pass_word);
    snprintf(buffer,MAX_BUFFER_SIZE,"%s\r\n",user_name);
    sendtoserver(mail_sock,buffer,strlen(buffer));
    getserverreply(mail_sock,buffer,MAX_BUFFER_SIZE);
    snprintf(buffer,MAX_BUFFER_SIZE,"%s\r\n",pass_word);
    sendtoserver(mail_sock,buffer,strlen(buffer));
    getserverreply(mail_sock,buffer,MAX_BUFFER_SIZE);

    //mail from
    snprintf(buffer,MAX_BUFFER_SIZE,"MAIL FROM:<%s>\r\n",sender);
    sendtoserver(mail_sock,buffer,strlen(buffer));
    getserverreply(mail_sock,buffer,MAX_BUFFER_SIZE);
    
    //reply to
    snprintf(buffer,MAX_BUFFER_SIZE,"RCPT TO:<%s>\r\n",sender);
    sendtoserver(mail_sock,buffer,strlen(buffer));
    getserverreply(mail_sock,buffer,MAX_BUFFER_SIZE);

    //data
    
	snprintf( buffer,MAX_BUFFER_SIZE, "DATA\r\n");
    
    sendtoserver(mail_sock,buffer,strlen(buffer));
    getserverreply(mail_sock,buffer,MAX_BUFFER_SIZE);
    #if 0
	snprintf( buffer,MAX_BUFFER_SIZE, "Subject: %s\r\n\r\n", subject );
    
    sendtoserver(mail_sock,buffer,strlen(buffer));

	/* send header, or this can be ignored. */
	snprintf( buffer,MAX_BUFFER_SIZE, "From: %s\r\n", sender);    
    sendtoserver(mail_sock,buffer,strlen(buffer));

    
	snprintf( buffer, MAX_BUFFER_SIZE,"To: %s\r\n", receiver);   
    sendtoserver(mail_sock,buffer,strlen(buffer));
	if( cc ) 
    {
        snprintf( buffer, MAX_BUFFER_SIZE,"Cc: %s\r\n", cc );      
        sendtoserver(mail_sock,buffer,strlen(buffer));
    }
    

	/* send each sentence */
	// Establish string and get the first token:
    #endif
	snprintf( buffer, MAX_BUFFER_SIZE,"\r\n\r\n.\r\n" );   
    sendtoserver(mail_sock,buffer,strlen(buffer));
    getserverreply(mail_sock,buffer,MAX_BUFFER_SIZE);

    //quit 
    snprintf(buffer,MAX_BUFFER_SIZE,"QUIT\r\n");
    getserverreply(mail_sock,buffer,MAX_BUFFER_SIZE);
    
    getserverreply(mail_sock,buffer,MAX_BUFFER_SIZE);
    getserverreply(mail_sock,buffer,MAX_BUFFER_SIZE);
    getserverreply(mail_sock,buffer,MAX_BUFFER_SIZE);
    DEBUG("11");
    return 0;
    
    
}

int main(int argc,char * argv[])
{
    sendmail("smtp.126.com",25,"zhang3122986",argv[1],NULL,"zhang3122986@126.com",NULL,"zhang3122986@126.com");
}
